﻿using MyCode.Project.Domain.Config;
using MyCode.Project.Domain.Message.Response.Common;
using MyCode.Project.Domain.Repositories;
using MyCode.Project.Infrastructure.Common;
using MyCode.Project.Infrastructure.Exceptions;
using MyCode.Project.Infrastructure.Search;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;

namespace MyCode.Project.Repositories.Common
{
    public class Repository<TEntity> : IRepository<TEntity> where TEntity : class,new()
    {
        private MyCodeSqlSugarClient _context;

        public Repository(MyCodeSqlSugarClient context)
        {
            this._context = context;

            if (SystemConfig.IfOutputSql)
            {
                //输出执行的语句
                this._context.Aop.OnLogExecuting = (sql, pars) =>
                {
                   
                    LogHelper.Info($"Sql:{sql}{Environment.NewLine}参数：{JsonConvert.SerializeObject(pars)}");

                    Console.WriteLine("底层仓储:" + context.GetHashCode());
                };
            }

            _context.Aop.OnLogExecuting = (sql, pars) =>
            {
                if (_context.TempItems == null)
                    _context.TempItems = new Dictionary<string, object>();
                if (_context.TempItems.Keys.Contains("logTime"))
                    _context.TempItems["logTime"]= DateTime.Now;
                else
                    _context.TempItems.Add("logTime", DateTime.Now);
            };

            this._context.Aop.OnLogExecuted = (sql, pars) =>
            {
                var starting = _context.TempItems["logTime"];
                DateTime startingTime = DateTime.Parse(starting.ToString());
                _context.TempItems.Remove("logTime");
                var completedTime = DateTime.Now;
                //TimeSpan timeSpan = 
                //得到总共执行时间
                var executeSecond = (completedTime - startingTime).TotalSeconds;

                if (executeSecond >10)
                {
                    string _txt =   WebConfigUtils.GetAppSettingsInfo("DingDingTxt");
                    var slowLog = _txt+ $"sql执行时间,执行时长：{executeSecond}{Environment.NewLine}Sql:{sql}{Environment.NewLine}参数：{JsonConvert.SerializeObject(pars)}";

                    LogHelper.Info(slowLog);
                    LogHelper.Info("参数值");
                    string txt = "";
                    if (pars != null && pars.Count()>0)
                    {
                        pars.ToList().ForEach(t =>
                        {
                            if (string.IsNullOrWhiteSpace(t.ParameterName))
                            {
                                t.ParameterName = "无";
                            }
                            txt += "参数名:" + t.ParameterName + "\t参数值:" + t.Value + "\n";
                        });
                    }
                    LogHelper.Info(txt);
                    //try
                    //{
                    //    if (executeSecond > 120)
                    //        DingDingHelper.SendMsg(_txt + $"发现慢sql,执行时长：{executeSecond},执行Sql:{sql}\n{txt} ");
                    //}
                    //catch
                    //{ }
                }


            };
        }

        #region 事务处理
        public void BeginTran()
        {
            this._context.Ado.BeginTran();
        }
        public void CommitTran()
        {
            this._context.Ado.CommitTran();
        }
        public void RollbackTran()
        {
            this._context.Ado.RollbackTran();
        }
        #endregion

        #region SelectListPage(查询分页)
        /// <summary>
        /// 例子 "select * from table where id=@id and name=@name",new {id=1,name="a"}
        /// </summary>

        public PageResult<T> SelectListPage<T>(string sql, int pageIndex, int pageSize, string order, object parameters = null) where T : class, new()
        {
            if (string.IsNullOrEmpty(order)) { throw new BaseException("排序字段不可空"); }

            var result = new PageResult<T>();

            int totalNum = 0;

            result.DataList = this._context.SqlQueryable<T>(sql).AddParameters(parameters).OrderBy(order).ToPageList(pageIndex, pageSize, ref totalNum);

            result.Total = totalNum;

            return result;
        }
        #endregion

        #region SelectListPage(查询分页)
        public PageResult<T> SelectListPage<T>(string sql, SearchCondition condition,int pageIndex,int pageSize, string order) where T : class, new()
        {
            var conditonModel = condition.BuildConditionSql();

            return SelectListPage<T>(sql + " where " + conditonModel.Sql, pageIndex, pageSize, order, conditonModel.ListParameter);
        }
        #endregion      

        #region ExecuteSqlCommand(执行命令)
        public int ExecuteSqlCommand(string sql, object parameters=null) {
			
            return this._context.Ado.ExecuteCommand(sql, parameters);

        }
        #endregion

        #region SelectFirst(返回单条记录)

        public TEntity SelectFirst(Expression<Func<TEntity, bool>> whereExpression)
        {
            return this._context.Queryable<TEntity>().With(SqlWith.NoLock).First(whereExpression); 
        }
        #endregion

        #region SelectFirst(用SQL返回单条记录)
        /// <summary>
        /// 例子 "select * from table where id=@id and name=@name",new {id=1,name="a"}
        /// </summary>
        public T SelectFirst<T>(string sql, object parameters=null)
        {
            return this._context.Ado.SqlQuerySingle<T>(sql, parameters);
        }
        #endregion

        #region SelectFirst(用SQL返回单条记录)
        public T SelectFirst<T>(string sql, SearchCondition searchCondition)
        {             
            var where = searchCondition.BuildConditionSql();

            return this._context.Ado.SqlQuerySingle<T>(sql + " where " + where.Sql, where.ListParameter);
        }
        #endregion     

        #region SelectList(用SQL返回多条记录)
        /// <summary>
        /// 例子 "select * from table where id=@id and name=@name",new {id=1,name="a"}
        /// </summary>
        public List<T> SelectList<T>(string sql,object parameters = null) 
        {
            return this._context.Ado.SqlQuery<T>(sql, parameters);
        }
        #endregion

        #region SelectTable(得到Table表数据)
        /// <summary>
        /// 得到Table表数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public DataTable SelectTable(string sql, object parameters = null)
        {
            return this._context.Ado.GetDataTable(sql,parameters);
        }
        #endregion

        #region SelectList(用SQL + 条件返回多条记录)
        public List<T> SelectList<T>(string strSql, SearchCondition where)
        {
            if (where == null)
            {
                return SelectList<T>(strSql);
            }
            var whereSql = where.BuildConditionSql();

            var sql = strSql + " where " + whereSql.Sql;

            return this.SelectList<T>(sql,whereSql.ListParameter);
        }
        #endregion

        #region SelectList(列表)
        public List<TEntity> SelectList(Expression<Func<TEntity, bool>> whereExpression=null)
        {
            return _context.Queryable<TEntity>().Where(whereExpression).With(SqlWith.NoLock).ToList();
        }
        #endregion

        #region SelectList(根据主键返回的列表)
        public List<TEntity> SelectList(List<Guid> ids)
        {
            return _context.Queryable<TEntity>().In(ids).With(SqlWith.NoLock).ToList();
        }
        #endregion 

        #region Count(得到数量)
        public int Count(Expression<Func<TEntity, bool>> predicate)
        {
            return this._context.Queryable<TEntity>().Where(predicate).With(SqlWith.NoLock).Count();
        }
        #endregion

        #region IsExist(根据表达式是否存在)
        public bool IsExist(Expression<Func<TEntity, bool>> whereExpression)
        {
            return _context.Queryable<TEntity>().Where(whereExpression).Any();
        }
        #endregion

        #region Add(添加)
        public void Add(TEntity instance,string tablename = null)
        {
            if (tablename == null)
            {
                this._context.Insertable(instance).ExecuteCommand();

                return;
            }

            this._context.Insertable(instance).AS(tablename).ExecuteCommand();

        }
        #endregion

        #region Add(批量添加实体)
        /// <summary>
        /// 批量添加实体
        /// </summary>
        /// <param name="entities">实体集合</param>
        public void Add(List<TEntity> entities,string tableName = null)
        {
            if (entities == null || entities.Count == 0) { return; }

            if(tableName == null) {

                this._context.Insertable(entities).ExecuteCommand();

                return;
            }

            this._context.Insertable(entities).AS(tableName).ExecuteCommand();
            
        }
        #endregion

        #region Update(单个的修改)
        public void Update(TEntity instance)
        {
            this._context.Updateable(instance).ExecuteCommand();
        }
        #endregion

        #region Update(修改一组对象)
        /// <summary>
        /// 修改一组对象
        /// </summary>
        /// <param name="updateObjs"></param>
        public void Update(List<TEntity> updateObjs)
        {
            if (updateObjs == null || updateObjs.Count == 0) { return; }

            this._context.Updateable(updateObjs).ExecuteCommand();
        }
        #endregion

        #region Update(按字段批量修改一组对象)
        public void Update(List<TEntity> updateObjs, Expression<Func<TEntity, object>> columns)
        {
            if(updateObjs.Count>0)
                this._context.Updateable(updateObjs).UpdateColumns(columns).ExecuteCommand();
        }
        #endregion

        #region Update(按字段批量修改一组对象)
        public void Update(IEnumerable<TEntity> updateObjs, Expression<Func<TEntity, object>> columns)
        {
            this._context.Updateable(updateObjs.ToList()).UpdateColumns(columns).ExecuteCommand();
        }
        #endregion 

        #region Update(按字段修改，满足条件的数据，批量修改的补充)
        /// <summary>
        /// 按字段修改，满足条件的数据，批量修改的补充。
        /// 例子：Update(it => new WorkProcess { Remark = "测试批量修改",SystemType = 0 },p => p.WorkProcessId ==Guid.Parse("7BDDBBD3-B1CD-4C25-93BA-D7BF22032108"));
        /// </summary>
        /// <param name="columns">要修改的列</param>
        /// <param name="whereExpression">要修改的条件</param>
        public int Update(Expression<Func<TEntity, TEntity>> columns, Expression<Func<TEntity, bool>> whereExpression)
        {
            return this._context.Updateable<TEntity>().UpdateColumns(columns).Where(whereExpression).ExecuteCommand();
        }
        #endregion

        #region Delete(根据表达式删除)
        /// <summary>
        /// 根据表达式删除
        /// </summary>
        /// <param name="whereExpression"></param>
        public int Delete(Expression<Func<TEntity, bool>> whereExpression)
        {
            return this._context.Deleteable<TEntity>().Where(whereExpression).ExecuteCommand();
        }
        #endregion

        #region DeleteByIds(根据一组ID删除)
        /// <summary>
        /// 根据ID删除
        /// </summary>
        /// <param name="ids"></param>
        public void DeleteByIds(dynamic[] ids)
        {
            this._context.Deleteable<TEntity>().In(ids).ExecuteCommand();
        }
        #endregion

        #region Queryable(得到一个更加灵活的查询对象)
        /// <summary>
        /// 得到一个更加灵活的查询对象
        /// </summary>
        /// <returns></returns>
        public ISugarQueryable<TEntity> Queryable()
        {
            return this._context.Queryable<TEntity>().With(SqlWith.NoLock);
        }
        #endregion

        #region 获取下拉列表 加条件
        /// <summary>
        /// 获取下拉列表
        /// </summary>
        /// <param name="valueField">值字段，例如：ID</param>
        /// <param name="textField">文本字段，例如：Name</param>
        /// <param name="orderField">排序字段，例如：Name</param>
        /// <param name="where">条件</param>
        /// <returns></returns>
        public List<ItemResult> GetDropdownList(string valueField, string textField, string orderField,SearchCondition where = null)
        {
            var sql = string.Format(@"
select
	ROW_NUMBER() over(order by {3}) as SortId,
	LOWER(CAST({0} as nvarchar(200))) as Value
	,{1} as Text 
from 
	{2}", valueField, textField, typeof(TEntity).Name, orderField);
            return where == null ? this.SelectList<ItemResult>(sql) : this.SelectList<ItemResult>(sql, where);
        }
        #endregion

        #region 获取下拉列表
        /// <summary>
        /// 获取下拉列表
        /// </summary>
        /// <param name="valueField">值字段，例如：ID</param>
        /// <param name="textField">文本字段，例如：Name</param>
        /// <param name="where">条件</param>
        /// <returns></returns>
        public List<ItemResult> GetDropdownList(string valueField, string textField, SearchCondition where = null)
        {
            var sql = string.Format(@"
select
	LOWER(CAST({0} as nvarchar(200))) as Value
	,{1} as Text 
from 
	{2}", valueField, textField, typeof(TEntity).Name);
            return where == null ? this.SelectList<ItemResult>(sql) : this.SelectList<ItemResult>(sql, where);
        }
        #endregion
    }
}
